package org.timemanager.view;

import org.afree.chart.renderer.category.BarRenderer;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.DialogInterface.OnShowListener;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnKeyListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
//import android.content.ClipData;
//import android.view.DragEvent;
//import android.view.View.DragShadowBuilder;
//import android.view.View.OnDragListener;

/**
 * the main activity in which user can view all category items,all event items,
 * all statistics and insert,delete,update category,event.
 */
public class TimeManagerActivity extends Activity {
    /** 
     * only when flinging more than FLING_X in the x axis
     *  do it show the category layout.
    */
	public static final int FLING_X=100;
	/**
	 * indicate whether the category item list is shown.
	 */
	private boolean isShowEventCategory;
	/**
	 * container to list all category item and a item to show all events 
	 * and a item to show unclassified events.
	 */
	private LinearLayout eventCategoryLayout;
	/**
	 * container to list all events of the specific category selected.
	 */
	private LinearLayout eventListLayout;
	/**
	 * used to debug visually.
	 * show a bar to indicate whether the left side of category section is visual
	 */
//	private TextView showCategory;
	private TextView categoryAddItem;
	/**
	 * when long clicking a category item,
	 * it appears a dialog to let user handle something with this category,
	 * and at this time,record the current category item 
	 * which is different from the current selected category item determining 
	 * which event list to be shown on the right side of the screen. 
	 */
	private TextView curCategoryItem;
	/**
	 * determining which category's event to be shown on the right side.
	 */
	private TextView curSeletedCategoryItem = null;
	/**
	 * current event block is used to mark which event to be updated.
	 */
	private LinearLayout curEventBlock;
	/**
	 * current expanded event block is used to mark which event to be shown operation.
	 * it means expanding at most one event item every time,
	 * when expanding a new event item and another event item already expended,
	 * then the old event is folded firstly
	 */
	private LinearLayout curExpandEventBlock = null;
	/**
	 * a editor to be added a new category
	 */
	private EditText categoryEditText;
	/**
	 * record whether editor is displayed.
	 */
	private boolean isShowCategoryEditor;
	private DatabaseTool databaseTool=null;
	/**
	 * there is a bug when user clear data in the setting panel,
	 * since to uninstall is to upload the application,
	 * to clear data is just to delete the database file,
	 * when clearing data,the widget can't be updated synchronically.
	 * so firstly configure the broadcast to listen the change but fail,
	 * secondly listen the file system's change 
	 * for clearing data is just to delete the /data/data/org.timemanager.view/databases direction
	 * but fail again.
	 * now it is a permanent bug,maybe make a mistake in architecture
	 */
	//private static MyFileObserver fileObserver;
	
	private TextView floatEventCategory;
	
	public static String SharedPreferences="time_back";
	public static String IsFirst="first";
	
	private DataExchange dataExchange;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	//Log.e("TimeManagerActivity","oncreate");
    	//requestWindowFeature(Window.FEATURE_NO_TITLE);
        super.onCreate(savedInstanceState);
        
        SharedPreferences sp=getSharedPreferences(SharedPreferences, 0);
        boolean isFirst=sp.getBoolean(IsFirst, true);
        Log.e("isFirst",isFirst+"--");
        if(isFirst){
        	Intent intent=new Intent(TimeManagerActivity.this,UserHelpActivity.class);
        	startActivity(intent);
        	sp.edit().putBoolean(IsFirst, false).commit();
        	finish();
        }
        
        initAllConfiguration();
//        fileObserver=new MyFileObserver("/data/data/org.timemanager.view/databases");
//        fileObserver.startWatching();
    }

	@Override
	protected void onStart() {
		//Log.e("TimeManagerActivity","onstart");
		super.onStart();
		initEventList();
	}
	@Override
	protected void onDestroy() {
		super.onDestroy();
		try{
			if(databaseTool!=null) databaseTool.close();
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
	
    @Override
	public boolean onCreateOptionsMenu(Menu menu) {
    	menu.add(0, R.string.export, 0, getText(R.string.export));
    	//since import is a reserved symbol in java
    	menu.add(0, R.string._import, 1, getText(R.string._import));
    	menu.add(1, R.layout.user_help, 2, getText(R.string.user_help));
    	menu.add(1, R.string.main_feedback, 3, getText(R.string.main_feedback));
		return super.onCreateOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch(item.getItemId()){
			case R.layout.user_help:
				Intent intent=new Intent(TimeManagerActivity.this, UserHelpActivity.class);
				startActivity(intent);
				finish();
				break;
			case R.string.main_feedback:
				Intent sendEmailIntent = new Intent(Intent.ACTION_SEND);
				sendEmailIntent.putExtra(Intent.EXTRA_EMAIL, 
						new String[]{"qizhou1990@gmail.com","byandong@gmail.com"});
				sendEmailIntent.putExtra(Intent.EXTRA_SUBJECT,
						getText(R.string.app_name).toString()+"  "+getText(R.string.main_feedback).toString());
				
				sendEmailIntent.setType("text/plain");
				startActivity(Intent.createChooser(sendEmailIntent,getText(R.string.main_feedback_select)));
				break;
			case R.string.export:
				new BackupDialog(TimeManagerActivity.this, 2, dataExchange,
						DatabaseTool.DATABASE_NAME + "." + dataExchange.getFileType()).show();
				break;
			case R.string._import:
				new BackupDialog(TimeManagerActivity.this, 1, dataExchange, null).show();
				break;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(resultCode!=RESULT_OK){
			return;
		}
		if(requestCode==R.id.add_event){
			Bundle bundle=data.getExtras();
			int eventId=bundle.getInt("eventId");
			String eventName=bundle.getString("eventName");
			int categoryId=bundle.getInt("categoryId");
			int curCategoryId= (Integer) eventListLayout.getTag(R.id.category_id);
			if(curCategoryId==-2 || curCategoryId==categoryId){
				LinearLayout eventItemBlock=makeEventItemBlock(eventName, 
	    				eventId, curCategoryId);
	    		eventListLayout.addView(eventItemBlock, new LinearLayout.LayoutParams(
	    				LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
			}
			if(bundle.getBoolean("newCategory")){
				String newCategoryName=bundle.getString("categoryName");
				TextView categoryItem=makeCategoryItem(newCategoryName, categoryId);
	            eventCategoryLayout.addView(categoryItem,
	            		eventCategoryLayout.getChildCount()-1,categoryLayoutParams);
	            //changeEventCategory(categoryId);
			}
		}
		else if(requestCode==R.id.event_update){
			Bundle bundle=data.getExtras();
			int eventId=bundle.getInt("eventId");
			String eventName=bundle.getString("eventName");
			int categoryId=bundle.getInt("categoryId");
			int curCategoryId= (Integer) eventListLayout.getTag(R.id.category_id);
			if(curCategoryId==-2 || curCategoryId==categoryId){
				((TextView)curEventBlock.findViewById(R.id.event_item)).setText(eventName);
			}else{
				eventListLayout.removeView(curEventBlock);
			}
		}
	}

	/**
     * configure once for all parameters
     */
    private void initAllConfiguration(){
    	setContentView(R.layout.event_list);
    	BarRenderer.setDefaultShadowsVisible(false);
    	/*
    	 * since category item is added dynamically,
    	 * so it need this layout parameter to control the frame
    	 */
		categoryLayoutParams=new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
		categoryLayoutParams.setMargins(0, 0, 3, 0);
		
        eventCategoryLayout=(LinearLayout) findViewById(R.id.event_category);
        eventListLayout=(LinearLayout) findViewById(R.id.event_list);
        
        /*
         * show category item list initially 
         */
        isShowEventCategory=true;
//        eventCategoryLayout.setVisibility(View.GONE);
        
//        showCategory= (TextView) findViewById(R.id.show_category);
//        showCategory.setOnClickListener(new View.OnClickListener() {
//			
//			public void onClick(View v) {
//				// TODO Auto-generated method stub
//				showEventCategory(!isShowEventCategory);
//			}
//		});
        
        initListener();
        dataExchange = new CSVExchange(this);
        databaseTool=new DatabaseTool(this);
        
//        findViewById(R.id.event_list_top).setOnDragListener(new OnDragListener() {
//			
//			public boolean onDrag(View v, DragEvent event) {
//				// TODO Auto-generated method stub
//				if(event.getAction()==DragEvent.ACTION_DROP){
//					View view = (View) event.getLocalState();
//					view.findViewById(R.id.event_item).setVisibility(View.VISIBLE);
//				}
//				return false;
//			}
//		});
        findViewById(R.id.event_scroll).setSoundEffectsEnabled(true);
        findViewById(R.id.event_scroll).setOnTouchListener(showCategoryTouchListenerInScroll);
        findViewById(R.id.category_scroll).setOnTouchListener(showCategoryTouchListenerInScroll);
        
        /*
         * start new activity to add a new event
         */
        findViewById(R.id.add_event).setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				Intent intent=new Intent(TimeManagerActivity.this,EventActivity.class);
				intent.setAction(EventActivity.ACTION_ADD);
				startActivityForResult(intent, R.id.add_event);
			}
		});
        /*
         * jump to daily static record
         */
        findViewById(R.id.view_analyze).setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				Intent intent=new Intent(TimeManagerActivity.this,DailyRecordActivity.class);
				startActivity(intent);
			}
		});
        
        floatEventCategory=(TextView) findViewById(R.id.float_event_category);
        floatEventCategory.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				int categoryId=(Integer) curSeletedCategoryItem.getTag(R.id.category_id);
				if(categoryId==-2){
					return;
				}
				Intent intent=new Intent(TimeManagerActivity.this,CategoryAnalyzeActivity.class);
				intent.putExtra("categoryId", categoryId);
				startActivity(intent);
			}
		});
        initAddCategory();
    }
    
    /**
     * use to restore sqlite database
     */
    public void resetViews(){
    	eventListLayout.setTag(R.id.category_id, null);
    	initEventList();
    	
		int curEventId=databaseTool.getLatestEventId();
		if(curEventId!=-1){
			StartRecord.updateCurDoing(this, curEventId);
		}
    }
    /**
     * initialize all category item view,
     * category id equal to -2 means all events,
     * -1 means unclassified events,
     * these two kind is not stored in the database.
     */
	private void initEventList()
    {   
		eventCategoryLayout.removeAllViews();
		
		
        TextView categoryItem=makeCategoryItem((String) getText(R.string.all_category), -2);
        eventCategoryLayout.addView(categoryItem,categoryLayoutParams);
         
        categoryItem=makeCategoryItem((String) getText(R.string.unclassified_category), -1);
        eventCategoryLayout.addView(categoryItem,categoryLayoutParams);
        
        Cursor allCategories=databaseTool.getCategories();
        while(allCategories.moveToNext()){
            categoryItem=makeCategoryItem(allCategories.getString(1), allCategories.getInt(0));
            eventCategoryLayout.addView(categoryItem,categoryLayoutParams);
        }
        
//        try{
//			allCategories.close();
//		}catch (Exception e) {
//			// TODO: handle exception
//		}
        eventListLayout.removeAllViews();
        Object object=eventListLayout.getTag(R.id.category_id);
        int categoryId=-2;
        if(object!=null){
        	categoryId=(Integer)object;
        }
        changeEventCategory(categoryId);
        
        isShowCategoryEditor=true;
        showCategoryEditor(false);
    }
	/**
	 * when add category button is clicked,
	 * then this add button is hidden and a text box is displayed.
	 */
	private void initAddCategory()
	{
        categoryAddItem=(TextView) getLayoutInflater().inflate(R.layout.category_item, null);
//        categoryAddItem.setText(getText(R.string.category_add));
        categoryAddItem.setText("+");
        categoryAddItem.setTypeface(null,Typeface.BOLD);
        categoryAddItem.setTextSize(25);
        categoryAddItem.setOnClickListener(new OnClickListener() {
			
			public void onClick(View v) {
				showCategoryEditor(true);
				categoryEditText.requestFocus();
			}
		});
        //eventCategoryLayout.addView(categoryAddItem,categoryLayoutParams);
        
        categoryEditText=new EditText(this);
        categoryEditText.setSingleLine();
        //categoryEditText.setHint(R.string.category_add_hint);
        categoryEditText.setOnKeyListener(new OnKeyListener() {
			
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if(keyCode==KeyEvent.KEYCODE_ENTER){
					addCategoryItem();
				}
				return false;
			}
		});
        
        //isShowCategoryEditor=false;
	}
	public void addCategoryItem(){
		if(!isShowCategoryEditor){
			return;
		}
		String newCategoryName=categoryEditText.getText().toString();
		newCategoryName=newCategoryName.trim();
		//Log.e("newCategoryName",newCategoryName+"_");
		if(newCategoryName==null || newCategoryName=="" ||
				newCategoryName.length()==0){
			Toast.makeText(TimeManagerActivity.this, 
					getText(R.string.category_add_no), Toast.LENGTH_SHORT).show();
		}
		else if(databaseTool.checkCategoryName(newCategoryName)!=-1){
			Toast.makeText(TimeManagerActivity.this, 
					getText(R.string.category_add_exist), Toast.LENGTH_SHORT).show();
		}
		else{
			TextView categoryItem=makeCategoryItem(newCategoryName, 
					(int) databaseTool.insertCategory(newCategoryName));
            eventCategoryLayout.addView(categoryItem,
            		eventCategoryLayout.getChildCount()-1,categoryLayoutParams);
            Toast.makeText(TimeManagerActivity.this, 
					getText(R.string.category_add_success), Toast.LENGTH_SHORT).show();
		}
		((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).
			hideSoftInputFromWindow(categoryEditText.getWindowToken(),0);
		showCategoryEditor(false);
	}
	/**
	 * when a category item view is clicked,
	 * then list all of events included.
	 * when a category item view is long clicked,
	 * then a dialog box is displayed to update its category name,delete it or view static chart.
	 * @param categoryType whose category to be displayed
	 * @return return means event list linear layout is about to redraw,
	 * false means there is no need to update.
	 */
	private boolean changeEventCategory(int categoryType){
		boolean resValue=false;
		/*
		 * if condition can not be replaced by eventListLayout.getTag(R.id.category_id)
		 * because if you have a empty event list then you add a new event item
		 * then you can also call this method
		 */
		if(eventListLayout.getChildCount()==0 ||
				(Integer)eventListLayout.getChildAt(0).getTag(R.id.category_id)!=categoryType){
				Cursor allEvents=null;
				if(categoryType==-2){
					allEvents=databaseTool.getAllEvents();
				}else{
					allEvents=databaseTool.getCategoryEvents(categoryType);
				}
				eventListLayout.removeAllViews();
		        eventListLayout.setTag(R.id.category_id, categoryType);
		        
		        while(allEvents.moveToNext()){
		    		LinearLayout eventItemBlock=makeEventItemBlock(allEvents.getString(1), 
		    				allEvents.getInt(0), categoryType);
		    		eventListLayout.addView(eventItemBlock, new LinearLayout.LayoutParams(
		    				LinearLayout.LayoutParams.FILL_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT));
		        }
//		        try{
//					allEvents.close();
//				}catch (Exception e) {
//					// TODO: handle exception
//				}
		        /*
		         * if selecting a category previously,
		         * then reset the category to be unselected state
		         */
		        if(curSeletedCategoryItem!=null){
		        	curSeletedCategoryItem.setBackgroundResource(
		        			R.drawable.category_item_unselected);
		        	/*
		        	 * note that its parameter int doesn't refer to color resource's id.
		        	 */
		        	curSeletedCategoryItem.setTextColor(Color.parseColor("#ffffff"));
		        }
		        /*
		         * get the current selected category item according to its id
		         */
		        int categoryItemIndex=2;
		        if(categoryType<0){
		        	categoryItemIndex+=categoryType;
		        }
		        else{
//		        	Log.e("categoryType",categoryType+"__");
		        	categoryItemIndex+=databaseTool.getCategoryPosition(categoryType);
		        }
//		        Log.e("categoryItemIndex",categoryItemIndex+"__");
		        curSeletedCategoryItem=(TextView) eventCategoryLayout.getChildAt(categoryItemIndex);
		        curSeletedCategoryItem.setBackgroundResource(R.drawable.category_item_selected);
		        curSeletedCategoryItem.setTextColor(Color.parseColor("#0000ff"));
		        
		        resValue= true;
		        
//		        if(curExpandEventBlock!=null){
//		        	curExpandEventBlock.findViewById(R.id.event_operate).setVisibility(View.GONE);
//		        	
//		        }
		        curExpandEventBlock=null;
		}
		
		/**
		 * when changing a category selected,
		 * it has the chance to check whether the category contains events. 
		 */
		TextView eventListEmpty=(TextView) findViewById(R.id.event_list_empty);
		if(eventListLayout.getChildCount()==0){
			eventListEmpty.setVisibility(View.VISIBLE);
		}else{
			eventListEmpty.setVisibility(View.GONE);
		}
		
		if(categoryType==-2){
			floatEventCategory.setVisibility(View.GONE);
		}else{
			floatEventCategory.setVisibility(View.VISIBLE);
		}
		return resValue;
	}
	/**
	 * whether to display add category button or text box.
	 * @param bShowCategoryEditor true means showing  text box,false means showing add button.
	 */
	private void showCategoryEditor(boolean bShowCategoryEditor){
		if(bShowCategoryEditor && !isShowCategoryEditor){
			isShowCategoryEditor=bShowCategoryEditor;
			eventCategoryLayout.removeView(categoryAddItem);
			eventCategoryLayout.addView(categoryEditText,categoryLayoutParams);
			categoryEditText.setText("");
		}
		else if(!bShowCategoryEditor && isShowCategoryEditor){
			isShowCategoryEditor=bShowCategoryEditor;
			eventCategoryLayout.addView(categoryAddItem,categoryLayoutParams);
			eventCategoryLayout.removeView(categoryEditText);
		}
	}
	/**
	 * whether to show left linear layout to display the category item list.
	 * @param bShowEventCategory true means showing category list,false means hiding category list.
	 */
    private void showEventCategory(boolean bShowEventCategory){
		if(bShowEventCategory && !isShowEventCategory){
			isShowEventCategory=bShowEventCategory;
			eventCategoryLayout.setVisibility(View.VISIBLE);
			//showCategory.setText(getText(R.string.hide_category));
		}else if(!bShowEventCategory && isShowEventCategory){
			isShowEventCategory=bShowEventCategory;
			eventCategoryLayout.setVisibility(View.GONE);
			//showCategory.setText(getText(R.string.show_category));
			
			//when hidden event category scroll view and showed it next time
			//there should display add text view instead of editor
			showCategoryEditor(false);
		}
    }
    /**
     * when scrolling in the screen towards left,it means showing category list,
     * when scrolling in the screen towards right,it means hiding category list.
     * @param e1 the motion event when touch down event occurs.
     * @param e2 the motion event when touch up event occurs.
     */
    private void showEventCategoryFromGesture(MotionEvent e1,MotionEvent e2){
    	if(Math.abs(e2.getRawX()-e1.getRawX())>Math.abs(e2.getRawY()-e1.getRawY())){
			if(e2.getRawX()>e1.getRawX()){
				showEventCategory(true);
			}else if(e2.getRawX()<e1.getRawX()){
				showEventCategory(false);
			}
		}
    }
    /**
     * general method to make a view to display a event's properties.
     * @param text the event name
     * @param eventId the event id
     * @param categoryId the event's category id
     * @return a view containing a event's information
     */
    private LinearLayout makeEventItemBlock(String text,int eventId,int categoryId){
    	LinearLayout eventItemBlock=(LinearLayout) getLayoutInflater().inflate(R.layout.event_item, null);
		TextView eventItem=(TextView) eventItemBlock.findViewById(R.id.event_item);
		eventItem.setText(text);
		eventItemBlock.setTag(R.id.event_id, eventId);
		eventItemBlock.setTag(R.id.category_id, categoryId);
		eventItemBlock.setOnTouchListener(showCategoryTouchListener);
		eventItemBlock.setOnClickListener(eventBlockClickListener);
		//eventItemBlock.setOnLongClickListener(eventBlockLongClickListener);
		
		eventItemBlock.findViewById(R.id.event_start).setOnClickListener(eventStartClickListener);
		eventItemBlock.findViewById(R.id.event_update).setOnClickListener(eventUpdateClickListener);
		eventItemBlock.findViewById(R.id.event_delete).setOnClickListener(eventDeleteClickListener);
		eventItemBlock.findViewById(R.id.event_view_trend).setOnClickListener(eventViewTrendClickListener);
		eventItemBlock.findViewById(R.id.event_operate).setVisibility(View.GONE);
		return eventItemBlock;
    }
    /**
     * general method to make a view to show a category's properties.
     * @param text the category name.
     * @param categoryId the category id.
     * @return a view containing a category's information.
     */
	private TextView makeCategoryItem(String text,int categoryId){
        TextView categoryItem=(TextView) getLayoutInflater().inflate(R.layout.category_item, null);
        categoryItem.setText(text);
        categoryItem.setTag(R.id.category_id, categoryId);
//        categoryItem.setOnDragListener(categoryItemDragListener);
        categoryItem.setOnClickListener(categoryItemClickListener);
        /*
         * when clicking all item and unclassified item,
         * it has't been implemented.
         */
        if(categoryId>0){
        	categoryItem.setOnLongClickListener(categoryItemLongClickListener);
        }
        categoryItem.setOnTouchListener(showCategoryTouchListener);
        
        return categoryItem;
	}
	
    @Override
	protected Dialog onCreateDialog(final int categoryId) {
    	final EditText renameEditText=(EditText) getLayoutInflater().inflate(
				R.layout.category_operate2, null);
    	
		renameEditText.setOnKeyListener(new OnKeyListener() {
			
			public boolean onKey(View v, int keyCode, KeyEvent event) {
				if(keyCode==KeyEvent.KEYCODE_ENTER){
					dismissDialog(categoryId);
				}
				return false;
			}
		});
		
		AlertDialog.Builder builder=new AlertDialog.Builder(TimeManagerActivity.this);
		builder.setView(renameEditText);
		builder.setPositiveButton(getText(R.string.category_delete), new DialogInterface.OnClickListener() {
			
			public void onClick(DialogInterface dialog, int which) {
				boolean hasEventItem=databaseTool.deleteCategory(categoryId);
				Toast.makeText(TimeManagerActivity.this, 
						getText(R.string.category_delete_success), Toast.LENGTH_SHORT).show();
				eventCategoryLayout.removeView(curCategoryItem);
				/*
				 * when delete this category item and current event list is displayed this category,
				 * then return to display all event item
				 */
				int showCategoryTyep=(Integer)(eventListLayout.getTag(R.id.category_id));
				int curCategoryType=(Integer)(curCategoryItem.getTag(R.id.category_id));
				if(showCategoryTyep==-1 && hasEventItem){
					eventListLayout.removeAllViews();
					changeEventCategory(-1);
				}
				if(showCategoryTyep==curCategoryType ){
					changeEventCategory(-2);
				}
				curCategoryItem=null;
				dismissDialog(categoryId);
			}
		});
		builder.setNegativeButton(getText(R.string.view_analyze), new DialogInterface.OnClickListener() {
			
			public void onClick(DialogInterface dialog, int which) {
				Intent intent=new Intent(TimeManagerActivity.this,CategoryAnalyzeActivity.class);
				intent.putExtra("categoryId", categoryId);
				startActivity(intent);
				dismissDialog(categoryId);
			}
		});
		AlertDialog dialog=builder.create();
		
		dialog.setOnShowListener(new OnShowListener() {
			
			public void onShow(DialogInterface dialog) {
				//renameEditText.setText("");
				renameEditText.setText(curCategoryItem.getText());
			}
		});
		dialog.setOnDismissListener(new OnDismissListener() {
			
			public void onDismiss(DialogInterface dialog) {
				/**
				 * when the category item is deleted from this dialog,
				 * then there is no need to update its name.
				 */
				if(curCategoryItem==null) return;
				String newCategoryName=renameEditText.getText().toString();
				newCategoryName=newCategoryName.trim();
				if(newCategoryName==null || newCategoryName=="" ||
						newCategoryName.length()==0){
//					Toast.makeText(TimeManagerActivity.this, 
//							getText(R.string.category_add_no), Toast.LENGTH_SHORT).show();
				}
				else if(newCategoryName.equals(curCategoryItem.getText().toString())){
					
				}
				else if(databaseTool.checkCategoryName(newCategoryName)!=-1){
					Toast.makeText(TimeManagerActivity.this, 
							getText(R.string.category_add_exist), Toast.LENGTH_SHORT).show();
				}
				else{
					databaseTool.updateCategory(categoryId, newCategoryName);
					Toast.makeText(TimeManagerActivity.this, 
							getText(R.string.category_rename_success), Toast.LENGTH_SHORT).show();
					curCategoryItem.setText(newCategoryName);
				}
			}
		});
		return dialog;
	}

    /**
     * initialize all listener.
     */
	private void initListener(){
		eventViewTrendClickListener=new OnClickListener() {
			
			public void onClick(View v) {
				LinearLayout eventBlock=(LinearLayout) v.getParent().getParent();
				int eventId=(Integer) eventBlock.getTag(R.id.event_id);
				Intent intent=new Intent(TimeManagerActivity.this,EventTrendAnalyzeActivity.class);
				intent.putExtra("eventId", eventId);
				intent.putExtra("eventName", 
						((TextView)eventBlock.findViewById(R.id.event_item)).getText().toString());
				startActivity(intent);
			}
		};
		eventStartClickListener=new OnClickListener() {
			
			public void onClick(View v) {
				LinearLayout eventBlock=(LinearLayout) v.getParent().getParent();
				if(StartRecord.startRecord(TimeManagerActivity.this,
						(Integer)eventBlock.getTag(R.id.event_id),
						((TextView) eventBlock.findViewById(R.id.event_item)).getText().toString())){
					Toast.makeText(TimeManagerActivity.this, getText(
							R.string.event_start_success), Toast.LENGTH_SHORT).show();
				}
			}
		};
		eventDeleteClickListener=new OnClickListener() {
			
			public void onClick(View v) {
				LinearLayout eventBlock=(LinearLayout) v.getParent().getParent();
				int deleteEventId=(Integer) eventBlock.getTag(R.id.event_id);
				if(deleteEventId==StartRecord.curEventId){
					Toast.makeText(TimeManagerActivity.this, 
							getText(R.string.event_delete_cur_doing), Toast.LENGTH_SHORT).show();
				}else{
					databaseTool.deleteEvent(deleteEventId);
					/*
					 * when a event is deleted,the widget should be updated
					 */
					TimeManagerWidget.clearItems();
					eventListLayout.removeView(eventBlock);
					Toast.makeText(TimeManagerActivity.this, 
							getText(R.string.event_delete_success), Toast.LENGTH_SHORT);
				}
				
			}
		};
		eventUpdateClickListener=new OnClickListener() {
			
			public void onClick(View v) {
				curEventBlock=(LinearLayout) v.getParent().getParent();
				Intent intent=new Intent(TimeManagerActivity.this,EventActivity.class);
				intent.setAction(EventActivity.ACTION_UPDATE);
				intent.putExtra("eventId", (Integer) curEventBlock.getTag(R.id.event_id));
				Log.e("eventId",(Integer) curEventBlock.getTag(R.id.event_id)+" __");
				startActivityForResult(intent, R.id.event_update);
			}
		};
    	categoryItemLongClickListener=new OnLongClickListener() {
			
			public boolean onLongClick(View v) {
				curCategoryItem=(TextView) v;
				showDialog((Integer) v.getTag(R.id.category_id));
				return false;
			}
		};
    	showCategoryTouchListenerInScroll=new OnTouchListener() {
//			private boolean isMove;
//			private MotionEvent e1;
			/*
			 * as for scroll view's touch event,it is a little strange
			 * when scrolled on its child view horizontally,it only receives action up message
			 * when scrolled across its some child views vertically,
			 * it receives action move ,action up message
			 * when scrolled in the area without child view,
			 * it receives action down,action move,action up message 
			 * and its parameter motion event object is always referenced object,
			 * which means the value of motion event object in action down,move,up is all the same
			 * maybe that is why it can not receive fling message
			 */
			public boolean onTouch(View v, MotionEvent event) {
				switch(event.getAction()){
					case MotionEvent.ACTION_DOWN:
						//Log.e("down", event.toString());
						addCategoryItem();
//						e1=MotionEvent.obtain(event);
//						isMove=false;
//						break;
//					case MotionEvent.ACTION_MOVE:
//						//Log.e("move", event.toString());
//						isMove=true;
//						break;
//					case MotionEvent.ACTION_UP:
//						//Log.e("up", event.toString());
//						if(isMove && e1!=null && event!=null){
//							showEventCategoryFromGesture(e1, event);
//							e1=null;
//							isMove=false;
//						}
						break;
				}
				return false;
			}
		};
    	/*
    	 * there is problem in making a new OnGestureListener to contain 
    	 * all click,long click,fling event,first it does not has view object,
    	 * the source event,then when implement OnGestureListener to add my own
    	 * source view object as private field then it does not work when scroll 
    	 * on event block linear layout,it only receives down,scroll message ignore
    	 * single tap up(simulated click event),long press(simulated long press) and
    	 * fling event message
    	 */
    	showCategoryTouchListener=new OnTouchListener() {
			
			public boolean onTouch(View view, MotionEvent event) {
				//return new GestureDetector(new EventGestureListener((LinearLayout) view)).onTouchEvent(event);
				if(event.getAction()==MotionEvent.ACTION_DOWN){
					addCategoryItem();
				}
				return false;
				//return showCategoryDetector.onTouchEvent(event);
			}
		};
    	showCategoryDetector=new GestureDetector(new OnGestureListener() {
			
			public boolean onSingleTapUp(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
			
			public void onShowPress(MotionEvent e) {
				// TODO Auto-generated method stub
			}
			
			public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
					float distanceY) {
				/*
				 * getRawX is global coordinate for whole screen window,
				 * while getX is relative to the current control
				 */
				if(e1!=null && e2!=null){
					showEventCategoryFromGesture(e1, e2);	
				}
				return true;
			}
			
			public void onLongPress(MotionEvent e) {
				// TODO Auto-generated method stub
			}
			
			public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
					float velocityY) {
				// TODO Auto-generated method stub
				return true;
			}
			
			public boolean onDown(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
		});
    	eventBlockClickListener=new OnClickListener() {
			
			public void onClick(View v) {
				LinearLayout eventOperatorLayout=(LinearLayout) v.findViewById(R.id.event_operate);
				eventOperatorLayout.setVisibility(eventOperatorLayout.getVisibility()==
						View.VISIBLE?View.GONE:View.VISIBLE);
				if(eventOperatorLayout.getVisibility()== View.VISIBLE 
						&& curExpandEventBlock!=null && curExpandEventBlock!=v){
					curExpandEventBlock.findViewById(R.id.event_operate).setVisibility(View.GONE);
				
				}
				curExpandEventBlock=(LinearLayout) v;
			}
		};
//    	eventBlockLongClickListener=new OnLongClickListener() {
//    		
//    		public boolean onLongClick(View v) {
//    			/**
//    			 * when the category scroll view is invisible and the event item is dragged,
//    			 * there is a bug to recover to be visible
//    			 */
//    			if(isShowEventCategory){
//    				int categoryType= (Integer) v.getTag(R.id.category_id); 
//    				TextView eventItem=(TextView) v.findViewById(R.id.event_item);
//        			if(categoryType!=-2) eventItem.setVisibility(View.INVISIBLE);
//        			ClipData data = ClipData.newPlainText("", "");
//        			DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(eventItem);
//        			v.startDrag(data, shadowBuilder, v, 0);
//        			v.findViewById(R.id.event_operate).setVisibility(View.GONE);
//    			}    			
//    			return false;
//    		}
//    	};
    	categoryItemClickListener=new OnClickListener() {
    		
    		public void onClick(View v) {
    			changeEventCategory((Integer) v.getTag(R.id.category_id));
    		}
    	};
//    	categoryItemDragListener =new OnDragListener() {
//    		Drawable enterShape = getResources().getDrawable(
//    				R.drawable.shape_enter);
//    		Drawable normalShape = getResources().getDrawable(R.drawable.shape_exit);
//
//    		public boolean onDrag(View curView, DragEvent event) {
//    			switch (event.getAction()) {
//    				case DragEvent.ACTION_DRAG_STARTED:
//    					break;
//    				case DragEvent.ACTION_DRAG_ENTERED:
//    					curView.setBackgroundDrawable(enterShape);
//    					break;
//    				case DragEvent.ACTION_DRAG_EXITED:
//    					curView.setBackgroundDrawable(normalShape);
//    					break;
//    				case DragEvent.ACTION_DROP:
//    					View srcView = (View) event.getLocalState();
//    					int eventId=(Integer) srcView.getTag(R.id.event_id);
//    					TextView eventItem=(TextView) srcView.findViewById(R.id.event_item);
//    					int curCategoryType= (Integer) curView.getTag(R.id.category_id);
//    					int srcCategoryType= (Integer) srcView.getTag(R.id.category_id);
//    					
//    					if(curCategoryType!=-2 && curCategoryType!=srcCategoryType){
//    						databaseTool.updateEventCategory(eventId, curCategoryType);
//    						if(srcCategoryType!=-2){
//    							eventListLayout.removeView(srcView);
//    						}
//    					}
//    					else{
//    						eventItem.setVisibility(View.VISIBLE);
//    					}
//    					break;
//    				case DragEvent.ACTION_DRAG_ENDED:
//    					curView.setBackgroundDrawable(normalShape);
//    				default:
//    					break;
//    			}
//    			return true;
//    		}
//    	};
    }
	LinearLayout.LayoutParams categoryLayoutParams;
	/**
	 * when scroll horizontal on the category list and event list,
	 * it changes the visibility of the category item list.
	 */
    private OnTouchListener showCategoryTouchListenerInScroll;
    /**
     * when scroll horizontal on the category item itself and the event item itself,
     * its parent view does not have the chance to handle the message according to the running,
     * though it would have responded based on the theory,
     * so here add it manually. 
     */
    private OnTouchListener showCategoryTouchListener;
    private GestureDetector showCategoryDetector;
    /**
     * start to do a new thing.
     */
    private OnClickListener eventStartClickListener;
    /**
     * jump to view a event's monthly trend static chart.
     */
    private OnClickListener eventViewTrendClickListener;
    /**
     * delete a event item,
     * indeed,it just change its used field to hide it,
     * because the previous records may refer to it.
     */
    private OnClickListener eventDeleteClickListener;
    /**
     * update a event
     */
    private OnClickListener eventUpdateClickListener;
    /**
     * when clicking on a event block which includes 
     * event name,button to start,update,delete this event and
     * view this event's monthly trend statistic chart.
     */
    private OnClickListener eventBlockClickListener;
    /**
     * when long clicking a event block,
     * it should have implemented drag and drop function to update the event's category,
     * but under SDK 3.0,there is not official support. 
     */
    //private OnLongClickListener eventBlockLongClickListener;
    /**
     * when clicking a category item,then show its events including.
     */
    private OnClickListener categoryItemClickListener;
    /**
     * when long clicking a category item,
     * then show a dialog to update,delete itself and view its statistic chart. 
     */
    private OnLongClickListener categoryItemLongClickListener;
    /**
     * only after Android 3.0.x does it support drag and drop
     */
//    private OnDragListener categoryItemDragListener;
}